{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55a24ffa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "============================================================\n",
      "正在初始化手写数字识别系统...\n",
      "✅ KNN模型加载成功 | 最佳邻居数: 6\n",
      "============================================================\n",
      "🚀 手写数字识别系统启动中...\n",
      "📊 算法类型: KNN机器学习\n",
      "🎯 识别范围: 数字 0-9\n",
      "============================================================\n",
      "✅ 系统初始化完成\n",
      "🌍 启动Web服务...\n",
      "📍 服务地址: http://localhost:8800\n",
      "⏹️  终止服务: Ctrl + C\n",
      "------------------------------------------------------------\n",
      "* Running on local URL:  http://0.0.0.0:8800\n",
      "* To create a public link, set `share=True` in `launch()`.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div><iframe src=\"http://localhost:8800/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "错误详情: 'NoneType' object has no attribute '__array_interface__'\n",
      "识别完成 → 数字: 1\n",
      "识别完成 → 数字: 9\n",
      "识别完成 → 数字: 9\n",
      "识别完成 → 数字: 0\n",
      "识别完成 → 数字: 1\n",
      "识别完成 → 数字: 4\n",
      "识别完成 → 数字: 4\n"
     ]
    }
   ],
   "source": [
    "import gradio as gr\n",
    "import pickle\n",
    "import numpy as np\n",
    "from PIL import Image\n",
    "\n",
    "print(\"=\" * 60)\n",
    "print(\"正在初始化手写数字识别系统...\")\n",
    "\n",
    "# 模型加载函数\n",
    "def load_knn_model(model_path='best_knn_model.pkl'):\n",
    "    \"\"\"加载预训练的KNN模型\"\"\"\n",
    "    try:\n",
    "        with open(model_path, 'rb') as model_file:\n",
    "            model = pickle.load(model_file)\n",
    "        print(f\"✅ KNN模型加载成功 | 最佳邻居数: {model.n_neighbors}\")\n",
    "        return model\n",
    "    except FileNotFoundError:\n",
    "        print(\"❌ 模型文件缺失: 请确保 best_knn_model.pkl 存在\")\n",
    "        return None\n",
    "    except Exception as error:\n",
    "        print(f\"❌ 模型加载异常: {error}\")\n",
    "        return None\n",
    "\n",
    "# 加载机器学习模型\n",
    "digit_recognizer = load_knn_model()\n",
    "\n",
    "class ImageProcessor:\n",
    "    \"\"\"图像预处理类\"\"\"\n",
    "    \n",
    "    @staticmethod\n",
    "    def convert_to_grayscale(image_data):\n",
    "        \"\"\"转换为灰度图像\"\"\"\n",
    "        if isinstance(image_data, dict):\n",
    "            pil_image = Image.fromarray(image_data[\"composite\"])\n",
    "        else:\n",
    "            pil_image = Image.fromarray(image_data)\n",
    "        \n",
    "        return pil_image.convert('L') if pil_image.mode != 'L' else pil_image\n",
    "    \n",
    "    @staticmethod\n",
    "    def resize_and_normalize(image, target_size=(8, 8)):\n",
    "        \"\"\"调整尺寸并归一化\"\"\"\n",
    "        resized_img = image.resize(target_size, Image.Resampling.LANCZOS)\n",
    "        pixel_array = np.array(resized_img)\n",
    "        \n",
    "        # 颜色反转处理\n",
    "        if np.mean(pixel_array) > 128:\n",
    "            pixel_array = 255 - pixel_array\n",
    "        \n",
    "        # 归一化到0-16范围\n",
    "        return (pixel_array / 255.0) * 16\n",
    "\n",
    "def process_handwriting_input(sketch_data):\n",
    "    \"\"\"处理手写输入数据\"\"\"\n",
    "    if sketch_data is None:\n",
    "        raise ValueError(\"请在画板上绘制数字\")\n",
    "    \n",
    "    # 图像预处理流程\n",
    "    gray_image = ImageProcessor.convert_to_grayscale(sketch_data)\n",
    "    processed_array = ImageProcessor.resize_and_normalize(gray_image)\n",
    "    \n",
    "    return processed_array.flatten().reshape(1, -1)\n",
    "\n",
    "def analyze_digit(sketch_input):\n",
    "    \"\"\"分析手写数字\"\"\"\n",
    "    if digit_recognizer is None:\n",
    "        return \"⚠️ 系统异常: 识别模型未正确加载\"\n",
    "    \n",
    "    try:\n",
    "        # 数据预处理\n",
    "        prepared_data = process_handwriting_input(sketch_input)\n",
    "        \n",
    "        # 数字预测\n",
    "        predicted_digit = digit_recognizer.predict(prepared_data)[0]\n",
    "        \n",
    "        # 结果格式化\n",
    "        result_message = f\"🔢 识别数字: {predicted_digit}\"\n",
    "        \n",
    "        # 置信度分析\n",
    "        if hasattr(digit_recognizer, 'predict_proba'):\n",
    "            probability_scores = digit_recognizer.predict_proba(prepared_data)[0]\n",
    "            main_confidence = probability_scores[predicted_digit]\n",
    "            result_message += f\"\\n🎯 可信程度: {main_confidence:.1%}\"\n",
    "            \n",
    "            # 显示备选结果\n",
    "            top_candidates = np.argsort(probability_scores)[-3:][::-1]\n",
    "            result_message += \"\\n\\n📈 候选数字:\"\n",
    "            for rank, candidate in enumerate(top_candidates):\n",
    "                confidence_level = probability_scores[candidate]\n",
    "                result_message += f\"\\n{rank+1}. 数字 {candidate}: {confidence_level:.1%}\"\n",
    "        \n",
    "        print(f\"识别完成 → 数字: {predicted_digit}\")\n",
    "        return result_message\n",
    "        \n",
    "    except Exception as e:\n",
    "        error_info = f\"❌ 处理异常: {str(e)}\"\n",
    "        print(f\"错误详情: {e}\")\n",
    "        return error_info\n",
    "\n",
    "def reset_canvas():\n",
    "    \"\"\"重置画布\"\"\"\n",
    "    return None\n",
    "\n",
    "# 创建交互界面\n",
    "app_interface = gr.Blocks(\n",
    "    title=\"智能手写数字识别\",\n",
    "    theme=gr.themes.Monochrome()\n",
    ")\n",
    "\n",
    "with app_interface:\n",
    "    # 页面标题\n",
    "    gr.Markdown(\"\"\"\n",
    "    # 🖋️ 智能手写数字识别\n",
    "    ### 基于KNN机器学习算法 | 支持数字0-9识别\n",
    "    \"\"\")\n",
    "    \n",
    "    # 主要内容区域\n",
    "    with gr.Row():\n",
    "        # 输入区域\n",
    "        with gr.Column():\n",
    "            gr.Markdown(\"### ✏️ 数字绘制区\")\n",
    "            \n",
    "            drawing_canvas = gr.Sketchpad(\n",
    "                label=\"请在此绘制单个数字\",\n",
    "                height=280,\n",
    "                width=280,\n",
    "                image_mode=\"L\",\n",
    "               \n",
    "                type=\"numpy\"\n",
    "            )\n",
    "            \n",
    "            # 操作按钮\n",
    "            with gr.Row():\n",
    "                analyze_button = gr.Button(\n",
    "                    \"🔍 识别数字\", \n",
    "                    variant=\"primary\"\n",
    "                )\n",
    "                reset_button = gr.Button(\n",
    "                    \"🔄 清除画布\", \n",
    "                    variant=\"secondary\"\n",
    "                )\n",
    "        \n",
    "        # 输出区域\n",
    "        with gr.Column():\n",
    "            gr.Markdown(\"### 📋 识别结果\")\n",
    "            \n",
    "            result_display = gr.Textbox(\n",
    "                label=\"分析结果\",\n",
    "                lines=7,\n",
    "                interactive=False,\n",
    "                show_copy_button=True\n",
    "            )\n",
    "    \n",
    "    # 使用说明\n",
    "    with gr.Accordion(\"💡 使用说明\", open=False):\n",
    "        gr.Markdown(\"\"\"\n",
    "        **操作指南:**\n",
    "        - 在左侧画板用鼠标绘制数字\n",
    "        - 点击\"识别数字\"按钮进行分析\n",
    "        - 查看右侧区域的识别结果\n",
    "        - 需要重新绘制时点击\"清除画布\"\n",
    "        \n",
    "        **绘制建议:**\n",
    "        - 尽量保持笔画连贯清晰\n",
    "        - 数字大小适中，占据画板主要区域\n",
    "        - 避免过于潦草或变形\n",
    "        \n",
    "        **技术信息:**\n",
    "        - 识别算法: K最近邻(K-Nearest Neighbors)\n",
    "        - 输入规格: 8×8像素灰度图像\n",
    "        - 输出内容: 识别结果及置信度\n",
    "        \"\"\")\n",
    "    \n",
    "    # 事件绑定\n",
    "    analyze_button.click(\n",
    "        fn=analyze_digit,\n",
    "        inputs=drawing_canvas,\n",
    "        outputs=result_display\n",
    "    )\n",
    "    \n",
    "    reset_button.click(\n",
    "        fn=reset_canvas,\n",
    "        inputs=[],\n",
    "        outputs=drawing_canvas\n",
    "    )\n",
    "\n",
    "# 应用程序入口\n",
    "if __name__ == \"__main__\":\n",
    "    print(\"=\" * 60)\n",
    "    print(\"🚀 手写数字识别系统启动中...\")\n",
    "    print(\"📊 算法类型: KNN机器学习\")\n",
    "    print(\"🎯 识别范围: 数字 0-9\")\n",
    "    print(\"=\" * 60)\n",
    "    \n",
    "    if digit_recognizer is not None:\n",
    "        print(\"✅ 系统初始化完成\")\n",
    "        print(\"🌍 启动Web服务...\")\n",
    "        print(\"📍 服务地址: http://localhost:8800\")\n",
    "        print(\"⏹️  终止服务: Ctrl + C\")\n",
    "        print(\"-\" * 60)\n",
    "        \n",
    "        # 启动Web应用\n",
    "        app_interface.launch(\n",
    "            server_name=\"0.0.0.0\",\n",
    "            server_port=8800,\n",
    "            share=False\n",
    "        )\n",
    "    else:\n",
    "        print(\"❌ 系统启动失败\")\n",
    "        print(\"\\n🔧 故障排查:\")\n",
    "        print(\"  1. 确认模型文件 best_knn_model.pkl 存在\")\n",
    "        print(\"  2. 检查文件权限和路径\")\n",
    "        print(\"  3. 验证模型文件完整性\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "78215cdf",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "寻找最优K值: 100%|██████████| 40/40 [00:03<00:00, 12.62it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "最优准确率: 0.9889\n",
      "对应的K值: 6\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from sklearn.datasets import load_digits\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "import pickle\n",
    "from tqdm import tqdm\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 加载手写数字数据集\n",
    "digits = load_digits()\n",
    "X = digits.data\n",
    "y = digits.target\n",
    "\n",
    "# 划分训练集和测试集\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n",
    "\n",
    "# 初始化变量\n",
    "best_accuracy = 0\n",
    "best_k = 0\n",
    "best_knn = None\n",
    "accuracy_list = []  # 存储每个K值的准确率\n",
    "\n",
    "# 遍历K值（1-40），用tqdm显示进度条\n",
    "for k in tqdm(range(1, 41), desc=\"寻找最优K值\"):\n",
    "    knn = KNeighborsClassifier(n_neighbors=k)\n",
    "    knn.fit(X_train, y_train)\n",
    "    accuracy = knn.score(X_test, y_test)\n",
    "    accuracy_list.append(accuracy)\n",
    "    # 更新最优模型\n",
    "    if accuracy > best_accuracy:\n",
    "        best_accuracy = accuracy\n",
    "        best_k = k\n",
    "        best_knn = knn\n",
    "\n",
    "# 保存最优KNN模型到pickle文件\n",
    "with open('best_knn_model.pkl', 'wb') as f:\n",
    "    pickle.dump(best_knn, f)\n",
    "\n",
    "# 绘制准确率随K值变化的图表并保存为PDF\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.plot(range(1, 41), accuracy_list, marker='o', linestyle='-')\n",
    "plt.title('Accuracy vs K Value')\n",
    "plt.xlabel('K Value')\n",
    "plt.ylabel('Accuracy')\n",
    "plt.grid(True)\n",
    "plt.savefig('accuracy_plot.pdf')\n",
    "\n",
    "# 打印最优结果\n",
    "print(f\"最优准确率: {best_accuracy:.4f}\")\n",
    "print(f\"对应的K值: {best_k}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "fabaf65f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting scikit-learn\n",
      "  Downloading scikit_learn-1.7.2-cp313-cp313-win_amd64.whl.metadata (11 kB)\n",
      "Requirement already satisfied: numpy>=1.22.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from scikit-learn) (2.2.6)\n",
      "Collecting scipy>=1.8.0 (from scikit-learn)\n",
      "  Downloading scipy-1.16.2-cp313-cp313-win_amd64.whl.metadata (60 kB)\n",
      "Collecting joblib>=1.2.0 (from scikit-learn)\n",
      "  Downloading joblib-1.5.2-py3-none-any.whl.metadata (5.6 kB)\n",
      "Collecting threadpoolctl>=3.1.0 (from scikit-learn)\n",
      "  Downloading threadpoolctl-3.6.0-py3-none-any.whl.metadata (13 kB)\n",
      "Downloading scikit_learn-1.7.2-cp313-cp313-win_amd64.whl (8.7 MB)\n",
      "   ---------------------------------------- 0.0/8.7 MB ? eta -:--:--\n",
      "   - -------------------------------------- 0.3/8.7 MB ? eta -:--:--\n",
      "   ------ --------------------------------- 1.3/8.7 MB 5.1 MB/s eta 0:00:02\n",
      "   ---------------------------------- ----- 7.6/8.7 MB 17.0 MB/s eta 0:00:01\n",
      "   ---------------------------------------- 8.7/8.7 MB 17.0 MB/s eta 0:00:00\n",
      "Downloading joblib-1.5.2-py3-none-any.whl (308 kB)\n",
      "Downloading scipy-1.16.2-cp313-cp313-win_amd64.whl (38.5 MB)\n",
      "   ---------------------------------------- 0.0/38.5 MB ? eta -:--:--\n",
      "   - -------------------------------------- 1.8/38.5 MB 148.4 MB/s eta 0:00:01\n",
      "   - -------------------------------------- 1.8/38.5 MB 148.4 MB/s eta 0:00:01\n",
      "   -- ------------------------------------- 2.1/38.5 MB 3.5 MB/s eta 0:00:11\n",
      "   -- ------------------------------------- 2.4/38.5 MB 2.6 MB/s eta 0:00:15\n",
      "   --- ------------------------------------ 3.1/38.5 MB 2.9 MB/s eta 0:00:13\n",
      "   ---- ----------------------------------- 3.9/38.5 MB 3.1 MB/s eta 0:00:12\n",
      "   ----- ---------------------------------- 5.8/38.5 MB 3.9 MB/s eta 0:00:09\n",
      "   -------- ------------------------------- 8.4/38.5 MB 5.1 MB/s eta 0:00:06\n",
      "   ------------ --------------------------- 11.8/38.5 MB 6.1 MB/s eta 0:00:05\n",
      "   ------------- -------------------------- 12.8/38.5 MB 6.1 MB/s eta 0:00:05\n",
      "   --------------- ------------------------ 15.2/38.5 MB 6.5 MB/s eta 0:00:04\n",
      "   --------------------------------- ------ 32.5/38.5 MB 13.0 MB/s eta 0:00:01\n",
      "   ---------------------------------------- 38.5/38.5 MB 14.6 MB/s eta 0:00:00\n",
      "Downloading threadpoolctl-3.6.0-py3-none-any.whl (18 kB)\n",
      "Installing collected packages: threadpoolctl, scipy, joblib, scikit-learn\n",
      "Successfully installed joblib-1.5.2 scikit-learn-1.7.2 scipy-1.16.2 threadpoolctl-3.6.0\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "[notice] A new release of pip is available: 24.3.1 -> 25.3\n",
      "[notice] To update, run: python.exe -m pip install --upgrade pip\n"
     ]
    }
   ],
   "source": [
    "pip install scikit-learn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "e35bdd55",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: gradio in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (5.49.1)\n",
      "Requirement already satisfied: aiofiles<25.0,>=22.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (24.1.0)\n",
      "Requirement already satisfied: anyio<5.0,>=3.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (4.11.0)\n",
      "Requirement already satisfied: audioop-lts<1.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.2.2)\n",
      "Requirement already satisfied: brotli>=1.1.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (1.1.0)\n",
      "Requirement already satisfied: fastapi<1.0,>=0.115.2 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.120.0)\n",
      "Requirement already satisfied: ffmpy in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.6.4)\n",
      "Requirement already satisfied: gradio-client==1.13.3 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (1.13.3)\n",
      "Requirement already satisfied: groovy~=0.1 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.1.2)\n",
      "Requirement already satisfied: httpx<1.0,>=0.24.1 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.28.1)\n",
      "Requirement already satisfied: huggingface-hub<2.0,>=0.33.5 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.36.0)\n",
      "Requirement already satisfied: jinja2<4.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (3.1.6)\n",
      "Requirement already satisfied: markupsafe<4.0,>=2.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (3.0.3)\n",
      "Requirement already satisfied: numpy<3.0,>=1.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (2.2.6)\n",
      "Requirement already satisfied: orjson~=3.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (3.11.4)\n",
      "Requirement already satisfied: packaging in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (25.0)\n",
      "Requirement already satisfied: pandas<3.0,>=1.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (2.3.0)\n",
      "Requirement already satisfied: pillow<12.0,>=8.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (11.2.1)\n",
      "Requirement already satisfied: pydantic<2.12,>=2.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (2.11.10)\n",
      "Requirement already satisfied: pydub in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.25.1)\n",
      "Requirement already satisfied: python-multipart>=0.0.18 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.0.20)\n",
      "Requirement already satisfied: pyyaml<7.0,>=5.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (6.0.3)\n",
      "Requirement already satisfied: ruff>=0.9.3 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.14.2)\n",
      "Requirement already satisfied: safehttpx<0.2.0,>=0.1.6 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.1.7)\n",
      "Requirement already satisfied: semantic-version~=2.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (2.10.0)\n",
      "Requirement already satisfied: starlette<1.0,>=0.40.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.48.0)\n",
      "Requirement already satisfied: tomlkit<0.14.0,>=0.12.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.13.3)\n",
      "Requirement already satisfied: typer<1.0,>=0.12 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.20.0)\n",
      "Requirement already satisfied: typing-extensions~=4.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (4.15.0)\n",
      "Requirement already satisfied: uvicorn>=0.14.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio) (0.38.0)\n",
      "Requirement already satisfied: fsspec in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio-client==1.13.3->gradio) (2025.9.0)\n",
      "Requirement already satisfied: websockets<16.0,>=13.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from gradio-client==1.13.3->gradio) (15.0.1)\n",
      "Requirement already satisfied: idna>=2.8 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from anyio<5.0,>=3.0->gradio) (3.10)\n",
      "Requirement already satisfied: sniffio>=1.1 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from anyio<5.0,>=3.0->gradio) (1.3.1)\n",
      "Requirement already satisfied: annotated-doc>=0.0.2 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from fastapi<1.0,>=0.115.2->gradio) (0.0.3)\n",
      "Requirement already satisfied: certifi in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from httpx<1.0,>=0.24.1->gradio) (2025.4.26)\n",
      "Requirement already satisfied: httpcore==1.* in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from httpx<1.0,>=0.24.1->gradio) (1.0.9)\n",
      "Requirement already satisfied: h11>=0.16 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from httpcore==1.*->httpx<1.0,>=0.24.1->gradio) (0.16.0)\n",
      "Requirement already satisfied: filelock in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from huggingface-hub<2.0,>=0.33.5->gradio) (3.20.0)\n",
      "Requirement already satisfied: requests in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from huggingface-hub<2.0,>=0.33.5->gradio) (2.32.3)\n",
      "Requirement already satisfied: tqdm>=4.42.1 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from huggingface-hub<2.0,>=0.33.5->gradio) (4.67.1)\n",
      "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from pandas<3.0,>=1.0->gradio) (2.9.0.post0)\n",
      "Requirement already satisfied: pytz>=2020.1 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from pandas<3.0,>=1.0->gradio) (2025.2)\n",
      "Requirement already satisfied: tzdata>=2022.7 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from pandas<3.0,>=1.0->gradio) (2025.2)\n",
      "Requirement already satisfied: annotated-types>=0.6.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from pydantic<2.12,>=2.0->gradio) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.33.2 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from pydantic<2.12,>=2.0->gradio) (2.33.2)\n",
      "Requirement already satisfied: typing-inspection>=0.4.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from pydantic<2.12,>=2.0->gradio) (0.4.2)\n",
      "Requirement already satisfied: click>=8.0.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from typer<1.0,>=0.12->gradio) (8.3.0)\n",
      "Requirement already satisfied: shellingham>=1.3.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from typer<1.0,>=0.12->gradio) (1.5.4)\n",
      "Requirement already satisfied: rich>=10.11.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from typer<1.0,>=0.12->gradio) (14.2.0)\n",
      "Requirement already satisfied: colorama in c:\\users\\y\\appdata\\roaming\\python\\python313\\site-packages (from click>=8.0.0->typer<1.0,>=0.12->gradio) (0.4.6)\n",
      "Requirement already satisfied: six>=1.5 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from python-dateutil>=2.8.2->pandas<3.0,>=1.0->gradio) (1.17.0)\n",
      "Requirement already satisfied: markdown-it-py>=2.2.0 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from rich>=10.11.0->typer<1.0,>=0.12->gradio) (4.0.0)\n",
      "Requirement already satisfied: pygments<3.0.0,>=2.13.0 in c:\\users\\y\\appdata\\roaming\\python\\python313\\site-packages (from rich>=10.11.0->typer<1.0,>=0.12->gradio) (2.19.2)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from requests->huggingface-hub<2.0,>=0.33.5->gradio) (3.4.2)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from requests->huggingface-hub<2.0,>=0.33.5->gradio) (2.4.0)\n",
      "Requirement already satisfied: mdurl~=0.1 in c:\\users\\y\\appdata\\local\\programs\\python\\python313\\lib\\site-packages (from markdown-it-py>=2.2.0->rich>=10.11.0->typer<1.0,>=0.12->gradio) (0.1.2)\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "[notice] A new release of pip is available: 24.3.1 -> 25.3\n",
      "[notice] To update, run: python.exe -m pip install --upgrade pip\n"
     ]
    }
   ],
   "source": [
    "pip install gradio\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
